
function deepClone(org, target) {
  var tar = target || {},
      // toStr = Reflect.toString,
      toStr = Object.prototype.toString,
      arrType = '[object Array]';

  for (var k in org) {
    if (org.hasOwnProperty(k)) {
      if (typeof org[k] === 'object' && org[k] !== null) {
        tar[k] = toStr.call(org[k]) === arrType ? []: {};
        deepClone(org[k], tar[k]);
      } else {
        tar[k] = org[k]
      }
    }
  }
  return tar;
}

function deepCloneES6(org, hashMap = new WeakMap()) {
  if (org == undefined || typeof org !== 'object') return org;

  if (org instanceof Date) return new Date(org);

  if (org instanceof RegExp) return new RegExp(org);

  const hashKey = hashMap.get(org);

  if (hashKey) return hashKey;

  const target = new org.constructor();

  hashMap.set(org, target);

  for (let k in org) {
    if (org.hasOwnProperty(k))
      target[k] = deepCloneES6(org[k], hashMap)
  }

  return target;
}



// 重写方法 就是在 Array 原型上写

/**
 * arr.forEach(function (item, index, array) {
 *   console.log(this.name);
 *   console.log(item, index, array);
 * }, obj)
 */

Array.prototype.myForEach = function (cb) {
  // console.log(this); // Array 调用 指向的array
  var _arr = this;
  var _len = _arr.length;
  // 第二个参数可能(不)传
  var _arg2 = arguments[1] || window;

  for (var i = 0; i < _len; i ++) {
    // 循环执行cb 回调函数 输出 item, index, array
    cb.apply(_arg2, [_arr[i], i, _arr]);
  }
}


// --------------------------------------------------


// var newArr = arr.map(function (item, index, array) {
  // console.log(this.name);
  // console.log(item, index, array);
//   return item;
// }, obj)

Array.prototype.myMap = function (cb) {
  var _arr = this;
  var _len = _arr.length;
  var _arg2 = arguments[1] || window;
  var _newArr = []; // 因为map 可以返回一个新数组
  var _item;
  var _res;

  for (var i = 0; i < _len; i ++) {
    _item = deepClone(_arr[i]); // 深拷贝单项
    _res = cb.apply(_arg2, [_item, i, _arr])
    _res && _newArr.push(_res); // 进行扩展
  }

  return _newArr;
}


// --------------------------------------------------


// var newArr = arr.filter(function (item, index, array) {
  // return true;
  // return false;
//   console.log(this.name);
//   return item.age > 25;
// }, obj)

Array.prototype.myFilter = function (cb) {
  var _arr = this;
  var _len = _arr.length;
  var _arg2 = arguments[1] || window;
  var _newArr = [];
  var _item;

  for (var i = 0; i < _len; i ++) {
    _item = deepClone(_arr[i]);
    cb.apply(_arg2, [_item, i, _arr]) ? _newArr.push(_item) : ''
  }

  return _newArr;
}


// --------------------------------------------------


// var res = arr.every(function (item, index, array) {
  // console.log(item, index, array);
  // console.log(this);
  // return true;
  // return false;
  // return item.age < 25;
// }, obj)

Array.prototype.myEvery = function (cb) {
  var _arr = this;
  var _len = _arr.length;
  var _arg2 = arguments[1] || window;
  var _res = true;

  for (var i = 0; i < _len; i ++) {
    if (!cb.apply(_arg2, [_arr[i], i, _arr])) {
      _res = false;
      break;
    }
  }

  return _res;
}


// --------------------------------------------------


// var res = arr.some(function (item, index, array) {
  // console.log(item, index, array);
  // console.log(this);
  // return true;
  // return false;
  // return item.age > 40;
// }, obj)

Array.prototype.mySome = function (cb) {
  var _arr = this;
  var _len = _arr.length;
  var _arg2 = arguments[1] || window;
  var _res = false;

  for (var i = 0; i < _len; i ++) {
    if (cb.apply(_arg2, [_arr[i], i, _arr])) {
      _res = true;
      break;
    }
  }

  return _res;
}


// --------------------------------------------------


// var initialValue = [{
//   name: '小明',
//   age: 12
// }];
// var i = 0;

// var newArr = arr.reduce(function (prev, item, index, array) {
//   console.log(prev === initialValue) // true
//   console.log(prev) // prev 可看作一个容器
//   item.age >= 25 && prev.push(item);
//   return prev;
// }, initialValue);

Array.prototype.myReduce = function (cb, initialValue) {
  var _arr = this;
  var _len = _arr.length;
  var _arg3 = arguments[2] || window; // 扩展可传第三参数
  var _item;

  for (var i = 0; i < _len; i ++) {
    _item = deepClone(_arr[i]);
    initialValue = cb.apply(_arg3, [initialValue, _item, i, _arr]);
  }

  return initialValue;
}


// --------------------------------------------------


Array.prototype.myReduceRight = function (cb, initialValue) {
  var _arr = this;
  var _len = _arr.length;
  var _arg3 = arguments[2] || window;
  var _item;

  for (var i = _len; i >= 0; i --) {
    _item = deepClone(_arr[i]);
    initialValue = cb.apply(_arg3, [initialValue, _item, i, _arr]);
  }

  return initialValue;
}
